#!/usr/bin/env python
# -*- coding: utf8 -*-

"""
Experimental Python development environment similar to Smalltalk's Workspace
"""

import cStringIO
import sys
from PyQt4.QtGui import QApplication
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import QEvent, Qt
from PyQt4.Qsci import QsciScintilla, QsciLexerPython

class Workspace(QsciScintilla):
    """Editor component with extended functionality:
    * Ctrl + p: print evaluation value of selected text
    * Ctrl + d: execute selected text
    """
    def __init__(self):
        QsciScintilla.__init__(self)
        font = QtGui.QFont()
        font.setFamily("Liberation Mono")
        font.setFixedPitch(True)
        font.setPointSize(10)
        fontmetrics = QtGui.QFontMetrics(font)

        lexer = QsciLexerPython()
        lexer.setDefaultFont(font)

        self.setFont(font)
        self.setLexer(lexer)
        self.resize(fontmetrics.width("0")*80, fontmetrics.height()*25)
        
        self.connect(self, QtCore.SIGNAL("print_it"),
            self.print_it)
        self.connect(self, QtCore.SIGNAL("do_it"),
            self.do_it)

    
    def event(self, event):
        """Add keyboard shortcuts
        """
        if (event.type() == QEvent.KeyPress) and \
            (event.modifiers() == Qt.ControlModifier):
            if (event.key() == Qt.Key_P):
                self.emit(QtCore.SIGNAL("print_it"))
                return True
            if (event.key() == Qt.Key_P):
                self.emit(QtCore.SIGNAL("do_it"))
                return True

        return QsciScintilla.event(self, event)
    
    def print_it(self):
        """Print evaluation value of selected text"""
        _, _, line, pos = self.getSelection()
        if line == -1:
            return
        code = str(self.selectedText())
        compiled = compile(code, '<string>', 'single')
        out_buffer = cStringIO.StringIO()
        stdout_safe = sys.stdout
        sys.stdout = out_buffer
        exec(compiled, {})
        sys.stdout = stdout_safe
        output = out_buffer.getvalue()
        num_lines = len(output.split())
        chars_in_last_line = len(output.split()[:-1])
        if (num_lines > 1):
            output = "\n" + output
        self.insertAt(output, line, pos)
        self.setSelection(line, pos, line+num_lines, chars_in_last_line)

    def do_it(self):
        """Execute selected text"""
        code = str(self.selectedText())
        if code == "":
            return
        compiled = compile(code, '<string>', 'single')
        exec(compiled, {})

if __name__ == "__main__":
    app = QApplication(sys.argv)
    editor = Workspace()
    editor.show()
    
    sys.exit(app.exec_())
